package cn.h8k.hj212.codec.impl;

import cn.h8k.hj212.codec.Hj212Validator;
import cn.h8k.hj212.constant.Hj212Constants;
import java.nio.charset.StandardCharsets;

/**
 * HJ212协议校验器默认实现
 * 可被继承以自定义校验行为
 */
public class DefaultHj212Validator implements Hj212Validator {
    
    private final boolean validateLength;
    private final boolean validateCrc;
    
    /**
     * 默认构造函数，启用所有校验
     */
    public DefaultHj212Validator() {
        this(true, true);
    }
    
    /**
     * 自定义校验选项的构造函数
     * @param validateLength 是否校验长度
     * @param validateCrc 是否校验CRC
     */
    public DefaultHj212Validator(boolean validateLength, boolean validateCrc) {
        this.validateLength = validateLength;
        this.validateCrc = validateCrc;
    }
    
    /**
     * 校验协议数据长度
     * @param data 协议数据
     * @param declaredLength 声明的长度
     * @return 是否校验通过
     */
    @Override
    public boolean validateLength(String data, int declaredLength) {
        if (!validateLength) {
            return true;
        }
        return data.length() == declaredLength;
    }
    
    /**
     * 校验协议CRC
     * @param data 协议数据
     * @param declaredCrc 声明的CRC
     * @return 是否校验通过
     */
    @Override
    public boolean validateCrc(String data, String declaredCrc) {
        if (!validateCrc) {
            return true;
        }
        String calculatedCrc = calculateCrc(data);
        return calculatedCrc.equalsIgnoreCase(declaredCrc);
    }
    
    /**
     * 计算CRC16校验码
     * @param text 需要校验的文本
     * @return CRC16校验码
     */
    @Override
    public String calculateCrc(String text) {
        byte[] bytes = text.getBytes(StandardCharsets.UTF_8);
        int crc = 0xffff;
        int dxs = 0xa001;
        
        for (byte b : bytes) {
            crc ^= (b & 0xff);
            for (int j = 0; j < 8; j++) {
                int sbit = crc & 0x0001;
                crc >>= 1;
                if (sbit == 1) {
                    crc ^= dxs;
                }
            }
        }
        
        return String.format("%04X", crc & 0xFFFF);
    }
    
    /**
     * 保护方法：子类可重写以自定义CRC计算算法
     * @param bytes 字节数组
     * @return CRC16校验码
     */
    protected String calculateCrcFromBytes(byte[] bytes) {
        int crc = 0xffff;
        int dxs = 0xa001;
        
        for (byte b : bytes) {
            crc ^= (b & 0xff);
            for (int j = 0; j < 8; j++) {
                int sbit = crc & 0x0001;
                crc >>= 1;
                if (sbit == 1) {
                    crc ^= dxs;
                }
            }
        }
        
        return String.format("%04X", crc & 0xFFFF);
    }
} 